package gosu;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

import org.jouvieje.FmodEx.Channel;
import org.jouvieje.FmodEx.Sound;
import org.jouvieje.FmodEx.Enumerations.FMOD_RESULT;
import static org.jouvieje.FmodEx.Enumerations.FMOD_RESULT.*;
import static org.jouvieje.FmodEx.Defines.FMOD_MODE.*;
import static org.jouvieje.FmodEx.Misc.BufferUtils.*;
import org.jouvieje.FmodEx.Structures.FMOD_CREATESOUNDEXINFO;
import static org.jouvieje.FmodEx.Enumerations.FMOD_CHANNELINDEX.*;

import static gosu.Gosu.FMOD;
import static gosu.Gosu.fmodCheck;
import static gosu.Gosu.relaxedFmodCheck;


public class Song {
  private Window _window;
  private Sound _sound;
  private Channel _channel;
  private float _volume;

  private ByteBuffer _buffer;

  public Song(Window window, String filename) {
    _window = window;
    _channel = new Channel();
    _sound = new Sound();
    _volume = 1;

    // Make sure FMOD is initialized
    Gosu.checkFmodInit();

    _buffer = Gosu.loadFileIntoMemory(filename);
    FMOD_CREATESOUNDEXINFO exinfo = FMOD_CREATESOUNDEXINFO.create();
    exinfo.setLength(_buffer.capacity());
    fmodCheck(FMOD.createStream(_buffer, FMOD_HARDWARE | FMOD_LOOP_NORMAL | FMOD_2D | FMOD_OPENMEMORY, exinfo, _sound));
    exinfo.release();
  }


  public void play() {
    fmodCheck(FMOD.playSound(FMOD_CHANNEL_FREE, _sound, false, _channel));
    fmodCheck(_channel.setVolume(_volume));
    FMOD.update();
  }


  public void stop() {
    relaxedFmodCheck(_channel.stop());
  }


  public boolean isPlaying() {
    if (_channel.isNull()) return false;

    ByteBuffer buffer = newByteBuffer(1);
    relaxedFmodCheck(_channel.isPlaying(buffer));
    return buffer.get(0) != 0;
  }


  public void setVolume(float volume) {
    _volume = volume;

    if (!_channel.isNull()) {
      relaxedFmodCheck(_channel.setVolume(volume));
    }
  }


  public float getVolume() {
    return _volume;
  }


  protected void finalize() {
    _sound.release();
  }
}
